<?php

declare(strict_types=1);

namespace App\Dao;

use App\Actions\ChatAction;
use App\Job\AutoAdReturnQueueJob;
use App\Job\OppoAdDataReturnQueueJob;
use App\Model\AuditIp;
use App\Model\ChatConfig;
use App\Model\Fate;
use App\Model\Level;
use App\Model\Order;
use App\Model\User;
use App\Model\UserCardPack;
use App\Model\UserChange;
use App\Model\UserChatLimit;
use App\Model\UserIdentity;
use App\Model\UserSuperVip;
use App\Model\UserTease;
use App\Model\UserVip;
use App\Services\JwtService;
use App\Utils\FunUtil;
use App\Utils\LoggerUtil;
use App\Utils\MemcacheClient;
use App\Utils\RedisClient;
use Hyperf\Context\ApplicationContext;
use Hyperf\Context\Context;
use Hyperf\DbConnection\Db;
use Psr\Container\ContainerExceptionInterface;
use Psr\Container\NotFoundExceptionInterface;
use stdClass;
use function Hyperf\Translation\trans;

class UserDao
{
    private static $instance;

    public static function getInstance()
    {
        if (!self::$instance) {
            self::$instance = Applicationcontext::getcontainer()->get(self::class);
        }
        return self::$instance;
    }

    // 更新session_id
    public function updateSessionId($user, $commonParams)
    {
        $appUpgrade = new AppUpgradeDao();
        if ($appUpgrade->isHideCall($commonParams["from"], $commonParams["version_code"], $commonParams['channel'])) {
            // 记录审核环境进来的用户ip
            AuditIp::recordIp($user['id'], $commonParams['channel']);
        }

        $user['session_id'] = $update['session_id'] = $this->createSessionId($user['id']);
        $user['version_code'] = $update['version_code'] = $commonParams['version_code'];

        // 更新用户设备信息
        $update['phone_makers'] = $commonParams['phone_makers'];
        if ($user['ext2']) {
            $ext2 = $user['ext2'];
            if (is_object($ext2)) {
                $ext2 = json_decode(json_encode($ext2), true);
            } elseif (is_string($ext2)) {
                $ext2 = json_decode($ext2, true);
            }
            $user['ext2'] = $ext2;
            $ext2['from'] = $commonParams['from'];
            $ext2['imei'] = $commonParams['imei'];
            $ext2['channel'] = $commonParams['channel'];
            $ext2['phone_brand'] = $commonParams['phone_brand'];
            $ext2['phone_makers'] = $commonParams['phone_makers'];
            $ext2['package'] = $commonParams['package'];
            $ext2['network_state'] = $commonParams['network_state'];
            $ext2['ip'] = FunUtil::getClientIp();
            $ext2['login_addr'] = $commonParams['login_addr'] ?? 0;
            $ext2['language'] = $commonParams['language'] ?? 'en';
            $update['ext2'] = json_encode($ext2);
        }

        /** 注册24小时内的用户 从其他渠道登录修改渠道号 */
        if ($commonParams['package'] == 'com.love.huanyu' || $commonParams['package'] == 'com.xun.liao') {
            if (($user['channel'] != $commonParams['channel']) && ($user['sex'] != 2)) {
                $t1 = date('Y-m-d H:i:s', $user['register_time']);
                $t2 = date('Y-m-d H:i:s', time());
                LoggerUtil::write("login-change", $user['id'] . '--' . $user['channel'] . '--' . $commonParams['channel'] . '--' . $t1 . '--' . $t2);

                if (
                    !empty($commonParams['channel'])
                    && (
                        (strpos($user['channel'], 'huanyu') === false
                            && strpos($user['channel'], 'xunyuan') === false
                            && !in_array($user['channel'], ['hybdin', 'hybdso'])
                        )
                        || (time() - $user['register_time'] >= 30 * 86400)
                    )
                ) {
                    $update['channel'] = $commonParams['channel'];
                    $update['register_time'] = time();
                    $queueData = [
                        'uid' => $user['id'],
                        'imei' => $commonParams['imei'],
                        'oaid' => $commonParams['oaid'],
                        'from' => $commonParams['from'],
                        'event_type' => 'active_register',
                        'channel' => $commonParams['channel'],
                        'model' => $commonParams['phone_brand'],
                        'ip' => FunUtil::getClientIp(),
                        'ctime' => time(),
                    ];
                    // RedisClient::getInstance()->lPush("queue:auto_ad_return_queue", json_encode($queueData));
                    // $this->queueService->push(new AutoAdReturnQueueJob(json_encode($queueData)));
                    pushQueueMessage(AutoAdReturnQueueJob::class, $queueData);

                    UserChange::query()->insert([
                        'uid' => $user['id'],
                        'channel' => $user['channel'],
                        'channel_new' => $update['channel'],
                        'register_time' => $user['register_time'],
                        'ctime' => time(),
                    ]);
                }
            }
        } else {
            if (time() - $user['register_time'] < 24 * 3600 && $user['channel'] != $commonParams['channel']) {
                $update['channel'] = $commonParams['channel'];
            }
        }

        if (empty($user['imei'])) {
            $update['imei'] = $commonParams['imei'];
        }

        if (empty($user['oaid'])) {
            $update['oaid'] = $commonParams['oaid'];
        }
        $user['login_time'] = $update['login_time'] = time();
        $user['last_login_id'] = $update['last_login_ip'] = FunUtil::getClientIp();
        User::query()->where('id', $user['id'])->update($update);
        MemcacheClient::getInstance()->delete('userInfo_' . $user['id']);
        return $user;
    }

    // 生成session_id
    public function createSessionId($user_id): bool|string
    {
        $current_time = time();

        $payload = [
            'iss' => 'jwt_admin', //该JWT的签发者
            'iat' => $current_time, //签发时间
            'exp' => $current_time + 3600 * 24 * 7, //过期时间
            'nbf' => $current_time, //该时间之前不接收处理该Token
            'uid' => $user_id, //面向的用户
            'jti' => md5(uniqid('JWT') . $current_time) //该Token唯一标识
        ];
        return JwtService::getToken($payload);
    }

    /**
     * Note - 获取用户信息
     * DateTime 2024/7/17 19:47
     * User Admin
     * @param mixed $uid
     * @param $cache //是否使用缓存
     * @param $language
     * @return array|\Hyperf\Database\Model\Builder|\Hyperf\Database\Model\Model|mixed|object
     * @throws \Psr\Container\ContainerExceptionInterface
     * @throws \Psr\Container\NotFoundExceptionInterface
     */
    public function findUserInfoCache(mixed $uid, $language = 'en', $cache = false)
    {
        $anchorEvaluateDao = new AnchorEvaluateDao();
        $userInfo = MemcacheClient::getInstance()->get("userInfo_" . $uid);
        $currentLoggedUid = Context::get('p_uid') ?? 0;
        if ($userInfo === false || !$cache) {
            $userInfo = User::query()->where('id', $uid)->first();
            $userInfo = modelToArray($userInfo);
            if (!empty($userInfo)) {
                if (isset($userInfo['language']) && $userInfo['language'] != '') {
                    $language = $userInfo['language'];
                }
                $userInfo['head_image'] = FunUtil::formatHeadImg($userInfo['head_image']);
                $userInfo['head_image_time'] = !empty($userInfo['head_image_time']) ? $userInfo['head_image_time'] : '';
                $userInfo['head_image_new'] = FunUtil::formatHeadImg($userInfo['head_image_new']);
                $userInfo['ext'] = !empty($userInfo['ext']) ? json_decode($userInfo['ext']) : '';
                if (empty($userInfo['ext'])) {
                    $userInfo['ext'] = new stdClass();
                }

                $userInfo['ext']->education = isset($userInfo['ext']->education) ? trans('information.education', [], $language)[$userInfo['ext']->education]['name'] : '';
                $userInfo['ext']->job = isset($userInfo['ext']->job) ? trans('information.job', [], $language)[$userInfo['ext']->job]['name'] : '';
                $userInfo['ext']->constellation = isset($userInfo['ext']->constellation) ? trans('constellation.' . $userInfo['ext']->constellation, [], $language) : '';
                $userInfo['ext']->weight = isset($userInfo['ext']->weight) && (string)$userInfo['ext']->weight != "" ? $userInfo['ext']->weight . 'kg' : '60kg';
                $userInfo['ext']->birthday = $userInfo['ext']->birthday ?? '';
                $userInfo['ext']->bust = isset($userInfo['ext']->bust) && (string)$userInfo['ext']->bust != "" ? (string)$userInfo['ext']->bust : 'C';


                $userInfo['ext2'] = !empty($userInfo['ext2']) ? json_decode($userInfo['ext2']) : '';
                $userInfo['signature'] = is_null($userInfo['signature']) ? "" : $userInfo['signature'];
                $userInfo['distance'] = mt_rand(3, 9) . '.' . mt_rand(0, 9) . mt_rand(0, 9);
                $userInfo['vip_buy_time'] = 0;
                $userInfo['vip_buy_pay_type'] = $userInfo['vip'] == 1 ? $this->getVipBuyType($userInfo['id']) : 0;
                $userInfo['once_buy_gold'] = $userInfo["already_buy_gold"];

                $userInfo['integrate_usable_count'] = $userInfo["integrate_usable_count"];
                $userInfo['integrate_freeze_count'] = $userInfo["integrate_freeze_count"];

                //如果用户是贵族，则返回贵族的到期时间
                if ($userInfo['noble'] == 1) {
                    $vipInfo = UserVip::query()->where('uid', $userInfo['id'])->where('status', 1)->orderBy('id', 'desc')->first();
                    if (!empty($vipInfo)) {
                        $userInfo['noble_over_time'] = date("Y-m-d", (int)$vipInfo['etime']);
                        $userInfo['noble_consume_type'] = intval($vipInfo['type']);
                    }
                }

                if ($uid == $currentLoggedUid && !empty($userInfo['ext'])) {
                    $ext = $userInfo['ext'];
                    $ext->activity_time = time();
                    $userInfo['ext'] = $ext;
                    // $this->update($uid,array('ext'=>json_encode($ext)));
                }

                if ($userInfo['sex'] == 2) {
                    $userInfo['first_recharge'] = 0;
                } else {
                    if ((new AppUpgradeDao())->isHideFirstRecharge($userInfo["from"], $userInfo["version_code"], $userInfo["channel"], $userInfo["last_login_ip"])) {
                        $userInfo['first_recharge'] = 0;
                    } else {
                        $userInfo['first_recharge'] = (new Order())->checkFirstRecharge($userInfo['id']);
                    }
                }
                if ($userInfo['sex'] == 1) {
                    MemcacheClient::getInstance()->set("userInfo_" . $uid, $userInfo, 300);
                }
            }
        }

        if (!empty($userInfo)) {
            $userInfo['is_identity'] = -1;
            $userInfo['alipay_id'] = '';
            $userInfo['video_price'] = 0;
            $userInfo['audio_price'] = 0;
            $userInfo['text_price'] = 0;
            $userInfo['auto_reply_status'] = 0;
            $userInfo['audio_greeting_url'] = '';
            $userInfo['audio_greeting_status'] = 0;
            $userInfo['audio_greeting_len'] = 0;
            $userInfo['connection_rate'] = 0;
            $userInfo['star_rank'] = 0;
            $userInfo['one_click_greet'] = 1;

            // TODO 临时处理公会女用户有一键打招呼功能
            if (in_array($userInfo['guild_num'], ['yq00147', 'yq00159'])) {
                //$userInfo['one_click_greet'] = 0;
            }

            if ($userInfo['sex'] == 2) {
                //主播昵称添加审核
                if ($currentLoggedUid == $uid && !empty($userInfo['nickname_new'])) {
                    $userInfo['nickname'] = $userInfo['nickname_new'];
                }

                $identity_info = (new UserIdentity())->getIdentityCache($uid);
                $anchorInfo = AnchorDao::getInstance()->findAnchorInfoCache($uid);
                $anchorInfo = modelToArray($anchorInfo);
                if (!empty($anchorInfo)) {
                    $userInfo['is_identity'] = 1;
                    $userInfo['call_show'] = $anchorInfo['call_show'];

                    $userInfo['call_show_type'] = $anchorInfo['call_show_type'];
                    $userInfo['alipay_id'] = $anchorInfo['alipay_id'];
                    $userInfo['video_price'] = $anchorInfo['video_price'];
                    $userInfo['audio_price'] = $anchorInfo['audio_price'];
                    $userInfo['text_price'] = $anchorInfo['greet_price'];
                    $userInfo['force_vip'] = $anchorInfo['force_vip'];
                    $userInfo['star_rank'] = $anchorInfo['star_rank'];
                    $userInfo['star_level'] = $anchorInfo['star_level'];
                    $userInfo['auto_reply_status'] = $anchorInfo['auto_reply_status'];
                    $userInfo['audio_greeting_url'] = $anchorInfo['audio_greeting_url'];
                    $userInfo['audio_greeting_status'] = $anchorInfo['audio_greeting_status'];
                    $userInfo['audio_greeting_len'] = $anchorInfo['audio_greeting_len'];
                    $userInfo['connection_rate'] = $anchorInfo['connection_rate'];
                    if ($language != 'zh-cn') {
                        $userInfo['evaluate'] = $anchorEvaluateDao->getData();
                    } else {
                        $userInfo['evaluate'] = $anchorInfo['evaluate'];
                    }
                    $userInfo['evaluate_color'] = $anchorInfo['evaluate_color'];


                    $userInfo['is_send_gift'] = $anchorInfo['is_send_gift'];    //女用户是否可以发送礼物

                    $userInfo['spread_rate'] = $anchorInfo['spread_rate'];

                    $userInfo['send_gift_rate'] = $anchorInfo['send_gift_rate'];

                    $userInfo['wx_new'] = $anchorInfo['wx_new'];
                    $userInfo['qq_new'] = $anchorInfo['qq_new'];
                    $userInfo['wx_status'] = $anchorInfo['wx_status'];  // 0待审核，2审核不通过
                    $userInfo['qq_status'] = $anchorInfo['qq_status'];  // 0待审核，2审核不通过
                    $userInfo['is_insideS'] = $anchorInfo['is_insideS'];  // 是否是打招呼女主播列表
                    $userInfo['videoFee'] = $anchorInfo['rate'] * $anchorInfo['video_price'];  // 是否是打招呼女主播列表
                    $userInfo['rate'] = $anchorInfo['rate'];

                } elseif (!empty($identity_info)) {
                    $userInfo['is_identity'] = (int)$identity_info['status'];  // 0待审核，2审核不通过
                    $userInfo['wx_status'] = 0;  // 0待审核，2审核不通过
                    $userInfo['qq_status'] = 0;  // 0待审核，2审核不通过
                } else {
                    $userInfo['wx_status'] = 0;  // 0待审核，2审核不通过
                    $userInfo['qq_status'] = 0;  // 0待审核，2审核不通过
                }
            }
            //自己访问则校验下等级
            if (!empty($uid)) {
                $level = (new Level())->getLevel($userInfo['integral'], $userInfo['sex']);
                if ($level != $userInfo['level']) {
                    User::query()->where('id', $uid)->update(['level' => $level]);
                    $userInfo['level'] = $level;
                }
            }
            //如果用户是贵族，则返回贵族的到期时间
            if ($userInfo['super_noble'] == 1) {
                $superVipInfo = UserSuperVip::query()->where('uid', $userInfo['id'])->where('status', 1)->first();
                if (!empty($superVipInfo)) {
                    $userInfo['super_noble_over_time'] = date("Y-m-d", (int)$superVipInfo['etime']);
                    $userInfo['super_noble_consume_type'] = intval($superVipInfo['type']);
                    $userInfo['super_free_video_time'] = intval($superVipInfo['free_video_time']);
                }
            }
        }

        return $userInfo;
    }

    private function getVipBuyType(mixed $id)
    {
        $return = 0;
        $info = Order::query()->where('uid', $id)
            ->where('consume_type', 1)
            ->where('notify_status', 1)
            ->where('pay_status', 1)
            ->orderBy('id', 'desc')
            ->value('type');
        if (!empty($info)) {
            $return = $info;
        }
        return $return;
    }

    // 注册插入数据
    public function registerInsertData(array $commonParams)
    {
        $ip = FunUtil::getClientIp();
        $current_time = time();
        $default_birthday = '1996-01-01';

        $data = [
            'appleId' => $commonParams['appleId'] ?: '',
            'channel' => $commonParams['channel'],
            'imei' => $commonParams['imei'],
            'imei_login' => $commonParams['imei_login'] ?? '',
            'oaid' => $commonParams['oaid'],
            'version_code' => $commonParams['version_code'],
            'from' => $commonParams['from'],
            'package' => $commonParams['package'],
            'is_binding' => empty($commonParams['phone']) ? 0 : 1,
            'register_ip' => $ip,
            'integrate_usable_count' => 0,
            'register_time' => $current_time,
            'register_time_new' => $current_time,
            'login_time' => $current_time,
            'online' => 0,
            'isdel' => 2, //未完善资料
            'phone_show' => 2,
            'qq_show' => 2,
            'weixin_show' => 2,
            'vip' => 0,
            'age' => FunUtil::birthday($default_birthday),
            'ext' => json_encode([
                'birthday' => $default_birthday,
                'constellation' => FunUtil::constellation($default_birthday)
            ]),
            'ext2' => json_encode([
                'from' => $commonParams['from'],
                'imei' => $commonParams['imei'],
                'channel' => $commonParams['channel'],
                'package' => $commonParams['package'],
                'phone_brand' => $commonParams['phone_brand'],
                'phone_makers' => $commonParams['phone_makers'],
                'network_state' => $commonParams['network_state'],
                'system_version' => $commonParams['system_version'],
                'ip' => $ip,
            ]),
            //额外参数
            'country' => $commonParams['country'],
            'province' => $commonParams['province'],
            'city' => $commonParams['city'],

            //必填项
            'nickname' => $commonParams['nickname'] ?? '',
            'password' => '',
            'phone' => $commonParams['phone'] ?? '',
            'wx_openid' => $commonParams['wx_openid'] ?? '',
            'wx_unionid' => $commonParams['wx_unionid'] ?? '',
            // 'inviteUid' => isset($commonParams['inviteUid']) ? intval($commonParams['inviteUid']) : 0,
            'inviteUid' => 0,
            'old_inviteUid' => 0,
            'lng' => $commonParams['lng'] ?: 0,
            'lat' => $commonParams['lat'] ?: 0,
            'guild_num' => $commonParams['guild_num'] ?? '',
            'phone_makers' => $commonParams['phone_makers'] ?? '',
            'is_audit' => $commonParams['is_audit'] ?? 0,
            'googleId' => $commonParams['googleId'] ?? '',
        ];

        $user = User::query()->create($data);
        if ($user) {
            switch ($commonParams['channel']) {
                case 'ybjyop';
                    $this->oppoAdDataReturn($commonParams['imei'], $commonParams['oaid'], $commonParams['package'], $user['id']);
                    break;
                default:
                    break;
            }
        }

        // 注册数据回传队列
        $queueData = [
            'uid' => $user['id'],
            'imei' => $commonParams['imei'],
            'oaid' => $commonParams['oaid'],
            'from' => $commonParams['from'],
            'event_type' => 'active_register',
            'channel' => $commonParams['channel'],
            'model' => $commonParams['phone_brand'],
            'ip' => $ip,
            'ctime' => time(),
        ];
        // RedisClient::getInstance()->lPush("queue:auto_ad_return_queue", json_encode($queueData));
        // $queueData = json_encode($queueData);
        // $this->queueService->push(new AutoAdReturnQueueJob($queueData));
        pushQueueMessage(AutoAdReturnQueueJob::class, $queueData);
        // LoggerUtil::write("auto_ad", $queueData);

        return $user;
    }

    public function oppoAdDataReturn($imei, $oaid, $pkg, $adId)
    {
        $data = [
            'imei' => $imei,
            'ouId' => $oaid,
            'pkg' => $pkg,
            'channel' => 1, //1、OPPO，2、一加，0、其他
            'timestamp' => microtime(true),
            'dataType' => 2,
            'type' => 0,
            'ascribeType' => 0,
            'adId' => $adId
        ];
        // $this->queueService->push(new OppoAdDataReturnQueueJob(json_encode($data)));
        pushQueueMessage(OppoAdDataReturnQueueJob::class, $data);
    }

    // 检查手机是否被注册
    public function checkPhone($phone)
    {
        return User::query()->where('phone', $phone)->where('isdel', 0)->where('is_binding', 1)->first();
    }


    // 获取用户在线状态
    public function getUserOnlineStatus($uid)
    {
        $user = User::query()->select(['id', 'is_disturb', 'sex', 'online', 'hide_call_status'])->where('id', $uid)->first();
        if ($user['online'] == 1) {
            if ($user['is_disturb'] == 1) {
                return '4';
            }
            // elseif ($user['status']==1 && $user['sex']==2){
            //     return '3';
            // }
        } elseif ($user['hide_call_status'] && $user['online'] == 2) {
            return '1';
        }
        return $user['online'];
    }

    /**
     * Note - 用户是否被搭讪
     * DateTime 2024/7/19 11:48
     * User Admin
     * @param $userIds //搭讪的用户id
     * @param $uid //被搭讪的用户id
     * @return array
     */
    public function readTease($userIds, $uid)
    {
        if (empty($userIds)) {
            return [];
        }
        if (!is_array($userIds)) {
            $userIds = explode(",", $userIds);
        }
        $res = UserTease::query()->where('uid', $uid)->whereIn('user_id', $userIds)->where('ctime', '>', strtotime(date("Ymd")))->get();
        if ($res->isNotEmpty()) {
            return array_column($res->toArray(), null, 'user_id');
        }
        return [];
    }


    // 判断用户审核状态
    public function inAudit($uid)
    {
        // $sql = "SELECT `from` type,version_code,channel,is_audit FROM tb_user WHERE id=$uid";
        // $rs = $this->findOne($sql);
        $rs = User::query()->selectRaw('`from` as type,version_code, channel, is_audit')->where('id', $uid)->first();
        $rs = modelToArray($rs);
        if (empty($rs)) {
            return true;
        }

        if ($rs['is_audit'] == 1) {
            return true;
        }

        $apps = (new AppupgradeDao())->getAuditingList();
        unset($rs['is_audit']);
        return in_array($rs, $apps);

    }

    // 根据用户id获取用户基本信息,包括tb_anchor表
    public function findBaseInfo($id)
    {
        $rs = User::query()->selectRaw('tb_user.id,tb_user.head_image,tb_user.nickname,tb_user.height,tb_user.age,tb_user.sex,tb_user.channel,tb_user.guild_num,tb_user.`online`,tb_anchor.force_vip,tb_anchor.video_url as call_video,tb_anchor.video_price,tb_anchor.audio_price,tb_anchor.greet_price text_price,tb_user.register_time,tb_user.province,tb_user.city,tb_user.ext,tb_user.is_cardAuth,case when tb_user.is_faceAuth=3 then 1 else tb_user.is_faceAuth end as is_faceAuth,tb_user.is_binding,tb_user.status,tb_user.isdel,tb_user.super_noble,tb_user.noble,tb_user.signature')
            ->leftJoin('tb_anchor', 'tb_user.id', '=', 'tb_anchor.uid')->where('tb_user.id', $id)->first();

        return modelToArray($rs);
    }

    /**
     * Note - 根据条件获取所有用户不区分男女
     * DateTime 2024/7/19 12:10
     * User Admin
     * @param $type
     * @param $uid
     * @param $in_audit
     * @param $page
     * @param $pageSize
     * @return mixed[]
     * @throws \Psr\Container\ContainerExceptionInterface
     * @throws \Psr\Container\NotFoundExceptionInterface
     */
    public function selectConditionUserList($type, $uid, $in_audit = 0, $page = 1, $pageSize = 20)
    {
        $query = User::query()
            ->select(['id', 'nickname', 'online', 'is_disturb', 'login_time'])
            ->where("isdel", 0)
            ->where("id", "<>", $uid);

        switch ($type) {
            default:
            case 1:
            case 3:
                break;
            case 2:
                $query->where('gender', 0);
                break;

            case 4:
                $query->where('register_time', '>=', strtotime('-30 days'));
                break;

            case 5:

                //关注
                $followId = FollowActionDao::getInstance()->getIdolsCache($uid, false);
                if (!empty($followId)) {
                    $query->whereIn('id', $followId);
                }
                break;
        }

        if ($in_audit > 0) {
            $query->where('in_audit', $in_audit);
        }

        return $query->orderBy('online', 'desc')->orderBy('login_time', 'desc')
            // ->skip(($page - 1) * $pageSize)
            // ->take($pageSize)
            ->forPage($page, $pageSize)
            ->get()->toArray();

//         $sql = <<<SQL
// SELECT id,nickname,online,is_disturb,login_time FROM {$this->table}
// WHERE isdel = 0 AND id<>{$uid} {$city_sql}
// ORDER BY online DESC,login_time DESC{$limit}
// SQL;
//         $pd = $this->createCommand($sql);
//         $pd->execute($bind_value);
//         $rs = $pd->fetchAll(PDO::FETCH_ASSOC);
//         $pd->closeCursor();
//         return $rs;
    }


    /**
     * 获取所有在线用户的uid
     * @param $sex
     * @return array
     */
    public function getOnlineUids($sex = 0)
    {
        // $where = "`online`>0";
        // if ($sex) {
        //     $where .= sprintf(" AND sex=%d", intval($sex));
        // }
        // $sql = "SELECT id AS uid FROM tb_user WHERE {$where}";
        // $pd = $this->createCommand($sql);
        // $pd->execute();
        // $rs = $pd->fetchAll(PDO::FETCH_ASSOC);
        // $pd->closeCursor();
        // array_column($rs, "uid");

        $query = User::query()->where('online', '>', 0);
        // 动态添加性别筛选条件
        if ($sex) {
            $query->where('sex', intval($sex));
        }

        // 执行查询并获取 uid 列
        $uids = $query->select('id as uid')
            ->pluck('uid')
            ->toArray();
        return $uids;


    }


    /**
     * Note - 获取审核环境的uid，采用一条SQL实现
     * DateTime 2024/8/19 14:58
     * User Admin
     * @return array
     */
    public function getAuditUidsEx()
    {
        // $sql = <<<SQL
        //     SELECT u.id
        //     FROM tb_user u
        //     LEFT JOIN tb_app_upgrade p ON u.from=p.type AND u.version_code=p.version_code AND u.channel=p.channel
        //     WHERE  p.is_auditing=1
        //     UNION
        //     SELECT id FROM tb_user WHERE is_audit=1
        // SQL;
        // $rs = $this->query($sql);
        // return array_column($rs, "id");
        return User::query()->from('tb_user AS u')
            ->selectRaw('u.id AS id')
            ->leftJoin('tb_app_upgrade AS p', function ($join) {
                $join->on('u.from', '=', 'p.type')
                    ->on('u.version_code', '=', 'p.version_code')
                    ->on('u.channel', '=', 'p.channel');
            })
            ->where(function ($query) {
                $query->where('p.is_auditing', 1);
            })
            ->union(function ($query) {
                $query->select('id')->from('tb_user')->where('is_audit', 1);
            })
            ->get()
            ->pluck('id')
            ->toArray();
    }


    /**
     * Note - 返回用户信息
     * DateTime 2024/7/19 12:33
     * User Admin
     * @param $language
     * @param $uid
     * @param int $list_type
     * @param array $userInfo
     * @return array
     * @throws ContainerExceptionInterface
     * @throws NotFoundExceptionInterface
     */
    public function getUserListInfo($language, $uid, $list_type = 0, $userInfo = [])
    {
        if (empty($userInfo)) {
            $userInfo = $this->findUserInfoCache($uid);
        }
        $user = [];
        $infoConfig = trans('information', [], $language);
        if (!empty($userInfo)) {
            $user['list_type'] = $list_type;
            $user['id'] = $userInfo['id'];
            $user['signature'] = $userInfo['signature'];
            $user['nickname'] = $userInfo['nickname'];
            $user['head_image'] = $userInfo['head_image'];
            $user['sex'] = $userInfo['sex'];
            $user['job'] = isset($userInfo['ext']->job) ? $infoConfig['job'][$userInfo['ext']->job]['name'] : '';
            $user['height'] = $userInfo['height'];
            $user['weight'] = isset($userInfo['ext']->weight) && (string)$userInfo['ext']->weight != "" ? $userInfo['ext']->weight : '60';
            $user['audio_greeting_url'] = '';
            $user['audio_time'] = 0;
            $user['pay_call_ranking'] = 0;
            if ($userInfo['sex'] == 2) {
                $user['is_insideS'] = $userInfo['is_insideS'];
                $user['evaluate'] = $userInfo['evaluate'];
                $user['evaluate_color'] = $userInfo['evaluate_color'];
                $user['bust'] = isset($userInfo['ext']->bust) && (string)$userInfo['ext']->bust != "" ? $userInfo['ext']->bust : 'C';
                if ($userInfo['is_identity'] == 1) {
                    $user['accept_video'] = $userInfo['accept_video'];
                    $user['accept_audio'] = $userInfo['accept_audio'];
                    $user['video_price'] = $userInfo['video_price'];
                    $user['audio_price'] = $userInfo['audio_price'];
                    $user['connection_rate'] = $userInfo['connection_rate'];
                    $user['auto_reply_status'] = $userInfo['auto_reply_status'];
                    if (!empty($userInfo['audio_greeting_url']) && $userInfo['audio_greeting_status'] == 1) {
                        $user['audio_greeting_url'] = $userInfo['audio_greeting_url'];
                        $user['audio_time'] = (int)$userInfo['audio_greeting_len'];
                    }
                }
                $user['pay_call_ranking'] = RankingDao::getInstance()->getPayCallRanding($uid);
            }
            $user['force_vip'] = $userInfo['force_vip'] ?? 0;
            $user['age'] = $userInfo['age'];
            $user['vip'] = $userInfo['vip'];
            $user['province'] = $userInfo['province'];
            $user['city'] = $userInfo['city'];
            $user['online'] = $userInfo['online'];
            $user['user_type'] = $userInfo['user_type'];
            $user['level'] = $userInfo['level'];
            $user['is_disturb'] = $userInfo['is_disturb'];
            $user['noble'] = $userInfo['noble'];
            $user['super_noble'] = $userInfo['super_noble'];
            $user['login_time'] = $userInfo['login_time'];
            $user['register_time'] = $userInfo['register_time'];
            $user['channel'] = $userInfo['channel'];
            $user['is_cardAuth'] = $userInfo['is_cardAuth'];
            $user['is_faceAuth'] = $userInfo['is_faceAuth'];
            $user['click_time'] = $userInfo['click_time'];
        }
        return $user;
    }


    /**
     * Note - 开启勿扰用户id列表
     * DateTime 2024/7/25 14:54
     * User Admin
     * @return mixed
     * @throws ContainerExceptionInterface
     * @throws NotFoundExceptionInterface
     */
    public function getDisturbList()
    {
        $uids = MemcacheClient::getInstance()->get("get_disturb_user_list_data");
        if (empty($uids)) {
            // $uids = [];
            // $sql = "select id from {$this->table} where `is_disturb` = ? ";
            // $pd = $this->createCommand($sql);
            // $pd->execute([1]);
            // $rs = $pd->fetchAll(PDO::FETCH_ASSOC);
            // $pd->closeCursor();
            // if (!empty($rs)) {
            //     foreach ($rs as $r) {
            //         $uids[] = $r['id'];
            //     }
            // }
            $uids = User::query()->where('is_disturb', 1)->pluck('id')->toArray();
            MemcacheClient::getInstance()->set("get_disturb_user_list_data", $uids, 300);
        }
        return $uids;
    }


    /**
     * Note - 是否是新人
     * DateTime 2024/7/25 18:15
     * User Admin
     * @param $uid
     * @return int
     */
    public function checkNewUser($uid)
    {
        $register_time = User::query()->where('id', $uid)->value('register_time');
        $is_new_user = 0;
        if ($register_time + 7 * 86400 >= time()) {
            $is_new_user = 1;
        }
        return $is_new_user;
    }


    /**
     * Note - 更新用户在线状态，和最新操作时间
     * DateTime 2024/7/30 12:14
     * User Admin
     * @param $uid
     * @param $online
     * @return int
     */
    public function updateUserOnline($uid, $online)
    {
        $update['online'] = $online;
        if ($online == 1) {
            // 0 不在线 1在线
            $update['auto_chat_online'] = $online;
        } else {
            // 最新操作时间
            $update['click_time'] = time();
        }
        return User::query()->where('id', $uid)->update($update);
    }


    /**
     * Note - 扣除用户的余额
     * DateTime 2024/8/2 10:42
     * User Admin
     * @param $user_id
     * @param $fare
     * @return mixed
     */
    public function reduceUserAccount($user_id, $fare)
    {
        // $sql = "update {$this->tableU} set gift_count = gift_count - ?,integral=integral+? where id = ? and gift_count>=?";
        // $pd = $this->createCommand($sql);
        // $pd->execute(array($fare, $fare, $user_id, $fare));
        // return $pd->rowCount();
        return User::query()->where('id', $user_id)->where('gift_count', '>=', $fare)
            ->update(['gift_count' => DB::raw('gift_count - ' . $fare), 'integral' => DB::raw('integral + ' . $fare)]);
    }

    /**
     * 扣除男用户用户聊币的余额
     * @param $user_id
     * @param $fare
     * @return int
     */
    public function reduceUserChatCount($user_id, $fare)
    {
        // $sql = "update {$this->tableU} set chat_count = chat_count - ? where id = ? and chat_count>=?";
        // $pd = $this->createCommand($sql);
        // $pd->execute(array($fare, $user_id, $fare));
        // return $pd->rowCount();
        return User::query()->where('id', $user_id)->where('chat_count', '>=', $fare)
            ->update(['chat_count' => DB::raw('chat_count - ' . $fare)]);
    }


    /**
     * Note - 增加男用户财富值，女用户魅力值
     * DateTime 2024/8/2 10:48
     * User Admin
     * @param $user_id
     * @param $anchor_id
     * @param $fare
     * @return int
     */
    public function addUserWealth($user_id, $anchor_id, $fare)
    {
        User::query()->where('id', $user_id)->orWhere('id', $anchor_id)->update(['wealth' => DB::raw('wealth + ' . $fare)]);
        $this->updateUserWealthLevel($user_id);
        $this->updateUserWealthLevel($anchor_id);
        return 1;
    }

    /**
     * Note - 维护用户等级（根据wealth字段，男用户财富值，女用户魅力值）
     * DateTime 2024/9/9 14:40
     * User Admin
     * @param $user_id
     * @param $wealth
     * @return int
     */
    public function updateUserWealthLevel($user_id, $wealth = 0)
    {
        if ($wealth <= 0) {
            $wealth = User::query()->where('id', $user_id)->value('wealth');
        }
        $level = getWealthLevel($wealth);
        User::query()->where('id', $user_id)->update(['level' => $level]);
    }


    /**
     * Note - 增加主播的余额 / 积分(更新用户积分)
     * DateTime 2024/8/2 11:15
     * User Admin
     * @param $anchor_id
     * @param $profit
     * @return mixed
     */
    public function addAnchorAccount($anchor_id, $profit)
    {
        // $sql = "update {$this->tableU} set integrate_usable_count = integrate_usable_count + ?,integral=integral+? where id = ?";
        // $pd = $this->createCommand($sql);
        // $pd->execute(array($profit, $profit, $anchor_id));
        // return $pd->rowCount();
        return User::query()->where('id', $anchor_id)->update([
            'integrate_usable_count' => DB::raw('integrate_usable_count + ' . $profit),
            'integral' => DB::raw('integral + ' . $profit)
        ]);
    }

    /**
     * Note - 更新用户余额
     * DateTime 2024/8/2 13:09
     * User Admin
     * @param $uid
     * @param $count
     * @return int
     */
    public function addUserGoldCount($uid, $count)
    {
        // try {
        //     $sql = "UPDATE `" . $this->table . "` SET gift_count = gift_count + $count,integral = integral + $count where id= ? limit 1";
        //     $pd = $this->createCommand($sql);
        //     return $pd->execute(array($uid));
        // } catch (PDOException $e) {
        //     Tool::JSON(\CodeData::NO_PROMPT, '-1', 'database error');
        // }

        return User::query()->where('id', $uid)->update(['gift_count' => DB::raw('gift_count + ' . $count), 'integral' => DB::raw('integral + ' . $count)]);
    }


    /**
     * Note - 获取一键打招呼用户列表
     * DateTime 2024/8/14 15:22
     * User Admin
     * @param $uid
     * @return array
     */
    public function getBitchUserIds($uid)
    {
        $redis = RedisClient::getInstance();
        $now_time = time();
        $keys = [];
        // $overTime = $this->findOneField("select param_value from tb_chat_config where param_key='user_reception_msg_interval'",'param_value');
        $overTime = ChatConfig::query()->where('param_key', 'user_reception_msg_interval')->value('param_value');

        for ($i = $now_time; $i > $now_time - $overTime; $i--) {
            $keys[] = "bitch_tease_user_ids_" . $i;
        }
        $excludeUid = $redis->mget($keys);
        $excludeUid = array_filter($excludeUid);

        // 前20秒内被搭讪过的男用户id
        $excludeUidArr = [];
        if (!empty($excludeUid)) {
            foreach ($excludeUid as $vv) {
                $excludeUidArr = array_merge($excludeUidArr, explode(",", $vv));
            }
        }
        // 超过消息限制的用户id
        $receiveUids = $this->getOverLimitUser();

        // 排除亲密度在5分以上、黑名单、给我发过消息、我关注的用户
        $mask = (new ChatAction())->getMaskUsers($uid) ?: [];
        $maskUids = array_merge($mask, $receiveUids, $excludeUidArr);

        $t0 = time() - 600; //注册(首次进入app的时间判断)10分钟内不被搭讪
        $time = strtotime(date("Ymd"));
        // 获取今日打招呼的用户id
        $teaseIds = UserTease::query()->where('uid', $uid)->where('ctime', '>', $time)->pluck('user_id')->toArray();

        // $where .= " and first_in_app_time < $t0 ";
        // $query->where('first_in_app_time', '<', $t0);
        // 排除今日推送过红线消息的用户
        // $where .= " and id not in (select recv_id from tb_fate where send_id={$uid} and ctime>={$time})";
        $fateIds = Fate::query()->where('send_id', $uid)->where('ctime', '>', $time)->pluck('recv_id')->toArray();

        // 排除风险用户
        // $where .= " and id not in (select uid from tb_user_chat_limit where status=1)";
        $limitIds = UserChatLimit::query()->where('status', 1)->pluck('uid')->toArray();
        $maskUids = array_merge($maskUids, $teaseIds, $fateIds, $limitIds);
        $maskUids = array_unique($maskUids);
        // oppo、vivo渠道不能被搭讪
        // $where .= " and channel != 'xy_vivo' and channel!='xy_oppo' and channel!='xy_bd' and json_extract(ext2, '$.channel') not in ('xy_vivo','xy_oppo','xy_bd') ";
        // $sql = "SELECT id,nickname FROM tb_user WHERE online>0 and sex=1 and isdel = 0 AND STATUS = 0 AND login_env = 0 AND in_audit = 0 AND is_audit = 0 and not_show=0 and id not in (select user_id from tb_user_tease where uid={$uid} and ctime>{$time}) {$where}  LIMIT 500";
        $data = User::query()->where('online', '>', 0)
            ->where('sex', 1)
            ->where('isdel', 0)
            ->where('first_in_app_time', '<', $t0)
            ->where('status', 0)
            ->where('login_env', 0)
            ->where('in_audit', 0)
            ->where('is_audit', 0)
            ->where('not_show', 0)
            ->whereNotIn('id', $maskUids)
            ->whereNotIn('channel', ['xy_vivo', 'xy_oppo', 'xy_bd'])
            ->whereRaw("json_extract(ext2, '$.channel') NOT IN ('xy_oppo', 'xy_vivo', 'xy_bd')")
            ->limit(500)
            ->get()->toArray();

        // $pd = $this->createCommand($sql);
        // $pd->execute(array(0));
        // $data = $pd->fetchAll(PDO::FETCH_ASSOC);

        if (!empty($data)) {
            shuffle($data);
            $returnData = array_slice($data, 0, 10);
            $re = $redis->set("bitch_tease_user_ids_" . $now_time, implode(",", array_column($returnData, "id")), intval($overTime));
            return $returnData;
        }

        return $data;
    }


    /**
     * 获取超过聊天限制的用户id
     * @return array
     */
    public function getOverLimitUser()
    {
        $now = time();
        // $chatConfig = $this->findOneField("select param_value from tb_chat_config where param_key='user_recv_limit'",'param_value');
        $chatConfig = ChatConfig::query()->where('param_key', 'user_recv_limit')->value('param_value');
        $chatConfig = json_decode($chatConfig);
        $limit_t = [];
        $t_arr = [];
        foreach ($chatConfig as $k => $v) {
            $t_arr[] = $k * 60; // 20*60=1200
            $limit_t[] = $k * 60 / $v; // 1200/26
        }

        // $sql = "select t.uid,t.user_id,count(DISTINCT t.uid) count from tb_user u left join tb_user_tease t on u.id=t.user_id and u.sex=1 and u.online>0 where u.click_time>{$now} - 3600 and t.ctime>{$now} - 3600 and case when u.register_time>{$now}-86400 and u.login_time>={$now} - {$t_arr[0]} then t.ctime>{$now} - {$limit_t[0]} when u.register_time>{$now}-86400 and u.login_time>={$now} - {$t_arr[2]} and u.login_time<{$now} - {$t_arr[1]} then t.ctime>{$now} - {$limit_t[2]} else t.ctime>{$now} - {$limit_t[1]} end  group by t.user_id";
        // $data = $this->query($sql);
        $data = User::query()->from('tb_user AS u')
            ->leftJoin('tb_user_tease as t', function ($join) use ($now) {
                $join->on('u.id', '=', 't.user_id')
                    ->where('u.sex', 1)
                    ->where('u.online', '>', 0)
                    ->where('u.click_time', '>', $now - 3600);
            })
            ->where('t.ctime', '>', $now - 3600)
            ->where(function ($query) use ($now, $t_arr, $limit_t) {
                $query->when("u.register_time > ($now- 86400) AND u.login_time >= ($now-$t_arr[0])", function ($q) use ($now, $limit_t) {
                    return $q->where('t.ctime', '>', $now - $limit_t[0]);
                })
                    ->when("u.register_time > ($now- 86400) AND u.login_time >= ($now - $t_arr[2])", function ($q2) use ($now, $limit_t) {
                        return $q2->where('t.ctime', '>', $now - $limit_t[2]);
                    }, function ($q1) use ($now, $limit_t) {
                        return $q1->where('t.ctime', '>', $now - $limit_t[1]);
                    });
            })
            ->select('t.user_id', 't.uid', DB::raw('COUNT(DISTINCT t.uid) as count'))
            ->groupBy('t.user_id')
            ->get();
        if (!empty($data)) {
            return array_column($data->toArray(), 'user_id');
        }
        return [];

    }


    /**
     * Note - 获取免费男用户
     * DateTime 2024/8/19 19:21
     * User Admin
     * @param $refuse_list -排除的用户id
     * @param $where -条件
     * @param int $call_type 1-视频 2-语音
     * @param int $is_over_card 0优先体验卡用户 1优先非体验卡用户
     * @return array
     */
    public function getFreeMaleCallUids($refuse_list, $where = '', $call_type = 1, $is_over_card = 0)
    {
        // $bindVal = [1, 0, 0, 1, 1, 0];
        // if (sizeof($refuse_list) > 0) {
        //     $where .= sprintf(" AND u.id NOT IN (%s)", implode(',', $refuse_list));
        // }

        if ($call_type == 1) {
            $accept_type = 'accept_video';
        } else {
            $accept_type = 'accept_audio';
        }

        $can_use_card = '';    // 可用体验卡男用户id
        // 有可用体验卡得男用户
        // $cardData = $this->query("SELECT c.id,c.uid FROM tb_user_card_pack c left join tb_user u on c.uid=u.id where c.card_type=1 and c.status=0 and u.sex = 1 AND u.isdel = 0 AND u.`status` = 0 AND u.`online`=1 group by c.uid");
        $cardData = UserCardPack::query()->from('tb_user_card_pack AS c')->leftJoin('tb_user AS u', 'c.uid', '=', 'u.id')
            ->selectRaw('c.id,c.uid')
            ->where('c.card_type', 1)
            ->where('c.status', 0)
            ->where('u.sex', 1)
            ->where('u.isdel', 0)
            ->where('u.status', 0)
            ->where('u.online', 1)
            ->groupBy('c.uid')
            ->get()->toArray();
        if (!empty($cardData)) {
            // 今日已用体验卡得男用户
            $uidss = array_column($cardData, 'uid');
            // $useCard = $this->query("SELECT id,uid FROM tb_user_card_pack where uid in ({$uidss}) and card_type=1 and status=1 and use_time >= ".strtotime(date("Ymd")));
            $useCard = UserCardPack::query()->whereIn('uid', $uidss)->where('card_type', 1)->where('status', 1)
                ->where('use_time', '>=', strtotime(date("Ymd")))->get()->toArray();
            if (!empty($useCard)) {
                $user_ids = array_diff(array_column($cardData, 'uid'), array_column($useCard, 'uid'));
                if (!empty($user_ids)) {
                    $can_use_card = implode(",", $user_ids);
                }
            }
        }

        $order = 'asc';
        if ($is_over_card) {
            $order = 'desc';
        }


        // $sql = "SELECT u.id AS uid,u.head_image,u.nickname,u.sex,u.level,u.province,u.city,u.gift_count,case when find_in_set(u.id,'{$can_use_card}') then 1 else 0 end order_card FROM {$this->table} u WHERE u.sex = ? AND u.isdel = ? AND u.`status` = ? AND u.`online` = ? AND {$accept_type} = ? AND u.is_disturb = ?{$where} ORDER BY order_card {$order},RAND()";
        // $bindVal = [1, 0, 0, 1, 1, 0];
        $result = User::query()
            ->selectRaw("id AS uid,head_image,nickname,sex,level,province,city,gift_count,case when find_in_set(id,'{$can_use_card}') then 1 else 0 end order_card")
            ->where('sex', 1)->where('isdel', 0)
            ->where('status', 0)->where('online', 1)
            ->where($accept_type, 1)->where('is_disturb', 0)
            ->when(!empty($refuse_list), function ($query) use ($refuse_list) {
                return $query->whereNotIn('id', $refuse_list);
            })
            ->when(!empty($where), function ($query) use ($where) {
                return $query->whereRaw($where);
            })
            ->orderBy('order_card', $order)
            ->orderByRaw('RAND()')
            ->get()->toArray();

        //die($sql);
        // $pd = $this->createCommand($sql);
        // $pd->execute($bindVal);
        // $result = $pd->fetchAll(PDO::FETCH_ASSOC);
        // $pd->closeCursor();
        $uids = [];
        $list = [];
        foreach ($result as $k => $v) {
            $uids[] = $v['uid'];
            $list[$v['uid']] = $v;
        }
        return [$uids, $list];
    }


    /**
     * Note - 更新用户recharge值和push_level
     * DateTime 2024/8/23 18:15
     * User Admin
     * @param $uid
     * @param $price
     * @return int
     */
    public function updateUserRecharge($uid, $price)
    {
        // $sql = "SELECT recharge FROM " . $this->table . " WHERE id=$uid LIMIT 1";
        // $recharge = $this->findOneField($sql, 'recharge', 0);
        // $push_level = ($recharge + $price >= 200) ? 3 : 2;
        // $sql = "UPDATE `" . $this->table . "` SET recharge = recharge + $price,push_level=$push_level where id= ? limit 1";
        // return $this->execute($sql, array($uid));
        $recharge = User::query()->where('id', $uid)->value('recharge');
        $push_level = ($recharge + $price >= 200) ? 3 : 2;
        return User::query()->where('id', $uid)->update(['recharge' => $recharge + $price, 'push_level' => $push_level]);
    }


    /**
     * Note - 获取所有在线男户的uid，去除华为和荣耀用户
     * DateTime 2024/8/30 17:04
     * User Admin
     * @return array
     */
    public function getOnlineMaleUids()
    {
        $time = strtotime(date('Y-m-d'));
        // 排除风险用户
        $where = " id not in (select uid from tb_user_chat_limit where status=1)";
        // $sql = "SELECT id AS uid FROM {$this->table} WHERE sex=1 AND login_env=0 AND is_audit=0 AND in_audit=0 AND status=0 AND isdel=0 AND auto_chat_online>0 AND channel<>'xy_oppo' AND channel<>'xy_vivo' AND channel NOT LIKE 'huawei%' AND login_time>=$time {$where}";
        // $pd = $this->createCommand($sql);
        // $pd->execute();
        // $rs = $pd->fetchAll(PDO::FETCH_ASSOC);
        // $pd->closeCursor();
        // return array_column($rs, "uid");
        return User::query()->select('id')
            ->where('sex', 1)
            ->where('login_env', 0)
            ->where('is_audit', 0)
            ->where('in_audit', 0)
            ->where('status', 0)
            ->where('isdel', 0)
            ->where('auto_chat_online', '>', 0)
            ->where('channel', '<>', 'xy_oppo')
            ->where('channel', '<>', 'xy_vivo')
            ->where('channel', 'NOT LIKE', 'huawei%')
            ->where('login_time', '>=', $time)
            ->whereNotIn('id', function ($query) {
                $query->from('tb_user_chat_limit')
                    ->select('uid')->where('status', 1);
            })
            ->pluck('id')->toArray();
    }


}